import { useCallback } from 'react';
import { ethers } from 'ethers';
import { useWeb3 } from './useWeb3';
import { useChain } from '@/context/ChainContext';
import toast from 'react-hot-toast';

// DTV Vesting Contract ABI (key functions)
const VESTING_CONTRACT_ABI = [
  // Read functions
  "function getBeneficiarySummary(address beneficiary) view returns (uint256 totalVested, uint256 totalReleased, uint256 totalReleasable, uint256 scheduleCount)",
  "function getBeneficiarySchedules(address beneficiary) view returns (bytes32[] scheduleIds)",
  "function getVestingSchedule(bytes32 scheduleId) view returns (address beneficiary, uint256 totalAmount, uint256 startTime, uint256 releasedAmount, uint256 releasableAmount, bool revoked, string category)",
  "function getVestingStats() view returns (uint256 totalSchedules, uint256 totalVesting, uint256 totalReleased, uint256 contractBalance)",
  "function getCategoryInfo(string category) view returns (uint256 limit, uint256 allocated, uint256 remaining)",
  
  // Write functions
  "function release(bytes32 scheduleId) external",
  "function releaseAll(address beneficiary) external",
  "function createVestingSchedulesBatch(address[] beneficiaries, uint256[] amounts, string[] categories) external",
  
  // Owner functions
  "function owner() view returns (address)",
  "function revokeVestingSchedule(bytes32 scheduleId) external",
  
  // Events
  "event VestingScheduleCreated(bytes32 indexed scheduleId, address indexed beneficiary, uint256 amount, string category)",
  "event TokensReleased(bytes32 indexed scheduleId, address indexed beneficiary, uint256 amount)",
  "event VestingScheduleRevoked(bytes32 indexed scheduleId, address indexed beneficiary)",
];

export function useVestingContract(contractAddress: string) {
  const { provider, signer, account, chainId, switchNetwork } = useWeb3();
  const { currentChain, chainConfig } = useChain();

  const getContract = useCallback((needsSigner = false) => {
    if (!provider) throw new Error('No provider available');
    if (needsSigner && !signer) throw new Error('No signer available');
    
    return new ethers.Contract(
      contractAddress,
      VESTING_CONTRACT_ABI,
      needsSigner ? signer : provider
    );
  }, [provider, signer, contractAddress]);

  const ensureCorrectNetwork = useCallback(async () => {
    const targetChainId = chainConfig.chainId;
    if (chainId !== targetChainId) {
      toast.loading(`Switching to ${chainConfig.displayName}...`);
      const switched = await switchNetwork(targetChainId);
      toast.dismiss();
      
      if (!switched) {
        throw new Error(`Please switch to ${chainConfig.displayName}`);
      }
    }
  }, [chainId, chainConfig, switchNetwork]);

  const releaseTokens = useCallback(async (scheduleId?: string) => {
    try {
      await ensureCorrectNetwork();
      
      const contract = getContract(true);
      
      let tx;
      if (scheduleId) {
        // Release specific schedule
        // Ensure scheduleId has 0x prefix
        const formattedScheduleId = scheduleId.startsWith('0x') ? scheduleId : `0x${scheduleId}`;
        tx = await contract.release(formattedScheduleId);
        toast.loading('Releasing tokens for specific schedule...');
      } else {
        // Release all available
        if (!account) throw new Error('No account connected');
        tx = await contract.releaseAll(account);
        toast.loading('Releasing all available tokens...');
      }
      
      const receipt = await tx.wait();
      toast.dismiss();
      toast.success('Tokens released successfully!');
      
      return {
        success: true,
        txHash: receipt.hash,
        receipt
      };
    } catch (error: any) {
      toast.dismiss();
      console.error('Release tokens error:', error);
      
      let errorMessage = 'Failed to release tokens';
      if (error.reason) {
        errorMessage = error.reason;
      } else if (error.message) {
        errorMessage = error.message;
      }
      
      toast.error(errorMessage);
      
      return {
        success: false,
        error: errorMessage
      };
    }
  }, [ensureCorrectNetwork, getContract, account]);

  const createVestingSchedules = useCallback(async (
    beneficiaries: string[],
    amounts: string[],
    categories: string[]
  ) => {
    try {
      await ensureCorrectNetwork();
      
      const contract = getContract(true);
      
      // Convert amounts to wei
      const amountsWei = amounts.map(amount => ethers.parseEther(amount));
      
      toast.loading('Creating vesting schedules...');
      
      const tx = await contract.createVestingSchedulesBatch(
        beneficiaries,
        amountsWei,
        categories
      );
      
      const receipt = await tx.wait();
      toast.dismiss();
      toast.success(`Created ${beneficiaries.length} vesting schedule(s) successfully!`);
      
      return {
        success: true,
        txHash: receipt.hash,
        receipt
      };
    } catch (error: any) {
      toast.dismiss();
      console.error('Create vesting schedules error:', error);
      
      let errorMessage = 'Failed to create vesting schedules';
      if (error.reason) {
        errorMessage = error.reason;
      } else if (error.message) {
        errorMessage = error.message;
      }
      
      toast.error(errorMessage);
      
      return {
        success: false,
        error: errorMessage
      };
    }
  }, [ensureCorrectNetwork, getContract]);

  const revokeVestingSchedule = useCallback(async (scheduleId: string) => {
    try {
      await ensureCorrectNetwork();
      
      const contract = getContract(true);
      
      // Ensure scheduleId has 0x prefix
      const formattedScheduleId = scheduleId.startsWith('0x') ? scheduleId : `0x${scheduleId}`;
      
      toast.loading('Revoking vesting schedule...');
      
      const tx = await contract.revokeVestingSchedule(formattedScheduleId);
      const receipt = await tx.wait();
      
      toast.dismiss();
      toast.success('Vesting schedule revoked successfully!');
      
      return {
        success: true,
        txHash: receipt.hash,
        receipt
      };
    } catch (error: any) {
      toast.dismiss();
      console.error('Revoke vesting schedule error:', error);
      
      let errorMessage = 'Failed to revoke vesting schedule';
      if (error.reason) {
        errorMessage = error.reason;
      } else if (error.message) {
        errorMessage = error.message;
      }
      
      toast.error(errorMessage);
      
      return {
        success: false,
        error: errorMessage
      };
    }
  }, [ensureCorrectNetwork, getContract]);

  const checkOwnership = useCallback(async () => {
    try {
      // Check if provider is available before trying to get contract
      if (!provider) {
        console.log('Provider not available yet for ownership check');
        return {
          owner: null,
          isOwner: false
        };
      }
      
      const contract = getContract(false);
      const owner = await contract.owner();
      return {
        owner,
        isOwner: account && owner.toLowerCase() === account.toLowerCase()
      };
    } catch (error) {
      console.error('Check ownership error:', error);
      return {
        owner: null,
        isOwner: false
      };
    }
  }, [getContract, account, provider]);

  return {
    releaseTokens,
    createVestingSchedules,
    revokeVestingSchedule,
    checkOwnership,
    ensureCorrectNetwork,
    isCorrectNetwork: chainId === chainConfig.chainId,
    account,
    chainId
  };
}